import { post, get } from '@/utils/requestUtil.js'

/**
 * @author liu_jshan
 * @date 20240324
 * @version 1.3
 * document 公共方法
 */

/**
 * 根据条件查询documents
 * @param {serviceName, collectionName, searchFactory} object
 *  serviceName: 服务名
 *  collectionName：表名
 *  searchFactory：查询条件 例如:[{
 *      feildName: ..., string
 *      feildValue: ..., 目前只支持string
 *      operate: ...  string 有eq、ne、like、in、lt、le、gt、ge八种
 *  }]
 * @returns documents
 */
export async function getDocumentsByCondition({ serviceName, collectionName, searchFactory }) {
    if (!serviceName || !collectionName) {
        return false
    }
    return await post(`/document/${serviceName}/condition`, {
        body: JSON.stringify({
            collectionName,
            searchFactory
        })
    })
}

/**
 * 根据id查询document
 * @param {id, serviceName, collectionName} object
 *  id: id
 *  serviceName: 服务名
 *  collectionName：表名
 * @returns document
 */
export async function getDocumentById({ id, serviceName, collectionName }) {
    if (!id || !serviceName || !collectionName) {
        return false
    }
    return await get(`/document/${serviceName}/get?id=${id}&collectionName=${collectionName}`)
}

/**
 * 根据配置好的sqlCode查询documents
 * @param {code, searchFactory} object
 *  code：sqlCode
 *  searchFactory：查询条件 例如:[{
 *      fieldName: ..., string
 *      fieldValue: ..., 目前只支持string
 *      operate: ...  string 有eq、ne、like、in、lt、le、gt、ge八种
 *  }]
 *  limit：分页条件 {startIndex, number}
 * @returns  {documents: [content], totalNumber}
 *  documents 结果集合
 *  totalNumber 数据总数
 */
export async function commonQueryByCode({ commandCode, searchFactory, limit, kvMap }) {
    if (!commandCode) {
        return false
    }
    return await post(`/document/command/${commandCode}`, {
        body: JSON.stringify({
            searchFactory,
            limit,
            kvMap
        })
    })
}

/**
 * 根据条件删除documents
 * @param {serviceName, collectionName, searchFactory} object
 *  serviceName: 服务名
 *  collectionName：表名
 *  searchFactory：查询条件 例如:[{
 *      fieldName: ..., string
 *      fieldValue: ..., 目前只支持string
 *      operate: ...  string 有eq、ne、like、in、lt、le、gt、ge八种
 *  }]
 */
export async function deleteDocumentsByCondition({ serviceName, collectionName, searchFactory }) {
    if (!serviceName || !collectionName) {
        return false
    }
    return await post(`/document/${serviceName}/delete/condition`, {
        body: JSON.stringify({
            collectionName,
            searchFactory
        })
    })
}


/**
 * 异步函数：根据ID更新文档
 * 
 * 该函数通过指定的服务名和集合名来更新数据库中的文档
 * 它接受 serviceName, collectionName, id 和 content 作为参数
 * 其中，serviceName 和 collectionName 用于确定要更新的集合属于哪个服务
 * id 是要更新的文档的唯一标识符，content 是包含要更新字段和值的对象
 * 
 * @param {Object} params - 函数参数对象
 * @param {string} params.serviceName - 服务名称
 * @param {string} params.collectionName - 集合名称
 * @param {string} params.id - 文档ID
 * @param {Object} params.content - 更新内容的对象
 * @returns {Promise} - 返回更新操作的结果Promise，如果无需更新则返回false
 */
export async function updateDocumentById({ serviceName, collectionName, id, content }) {
    // 创建一个空数组，用于存储更新操作的配置
    let updateFactory = []
    
    // 遍历content对象，生成更新操作的配置
    content && Object.keys(content).forEach(key => {
        // 忽略id字段，因为id是文档的唯一标识，不应作为更新内容
        if (key !== 'id') {
            updateFactory.push({
                fieldName: key,
                fieldValue: content[key]
            })
        }
    })
    
    // 如果有需要更新的字段
    if (updateFactory.length > 0) {
        // 调用updateFields函数执行更新操作，并返回操作结果
        return await updateFields({
            serviceName,
            collectionName,
            searchFactory: [
                {
                    fieldName: 'id',
                    fieldValue: id,
                    operate: 'eq'
                }
            ],
            updateFactory
        })
    } else {
        // 如果没有需要更新的字段，返回false
        return false
    }
}

/**
 * 异步更新指定集合中的字段。
 * 
 * 该函数向特定端点发送POST请求，尝试根据给定条件更新集合中的文档。
 * 它主要依赖四个参数：serviceName、collectionName、searchFactory 和 updateFactory。其中，serviceName 和 collectionName 用于定位要更新的集合；
 * searchFactory 定义了要更新的文档的搜索条件；而 updateFactory 指定了对文档进行的更新操作。
 * 
 * @param {Object} params - 更新操作的参数对象。
 * @param {string} params.serviceName - 服务名称，用于定位服务实例。不能为空。
 * @param {string} params.collectionName - 集合名称，用于指定要更新的集合。不能为空。
 * @param {Function} params.searchFactory - 生成搜索条件的函数，用于确定哪些文档需要更新。
 * @param {Function} params.updateFactory - 生成更新操作的函数，用于指定如何更新文档。
 * @returns {Promise<boolean>} - 返回一个 Promise，如果更新操作成功则解析为 true，否则解析为 false。
 */
export async function updateFields({ serviceName, collectionName, searchFactory, updateFactory}) {
    // 检查 serviceName 和 collectionName 是否已提供，因为它们对于定位目标集合是必需的。
    if (!serviceName || !collectionName) {
        return false
    }
    // 向服务器发送 POST 请求，请求更新符合指定条件的集合中的文档。
    return await post(`/document/${serviceName}/update/condition`, {
        body: JSON.stringify({
            collectionName,
            searchFactory,
            updateFactory
        })
    })
}

/**
 * 异步函数：创建文档
 * 
 * 该函数用于向指定的服务和集合中创建一个新的文档
 * 它通过POST请求发送文档内容到服务器
 * 
 * @param {Object} params - 函数接收的对象参数
 * @param {string} params.serviceName - 服务名称，用于指定操作的服务
 * @param {string} params.collectionName - 集合名称，用于指定操作的集合
 * @param {Object} params.content - 文档内容，将被转换为JSON字符串发送
 * @returns {Promise<boolean>} - 返回一个Promise对象，表示文档创建操作的结果
 * 如果serviceName或collectionName为空，则返回false；否则返回POST请求的结果
 */
export async function createDocument({ serviceName, collectionName, content}) {
    // 检查serviceName和collectionName是否为空，如果任一为空，则返回false
    if (!serviceName || !collectionName) {
        return false
    }
    // 发起POST请求，创建文档
    // 请求的URL包含服务名称和集合名称，请求体包含文档内容的JSON字符串
    return await post(`/document/${serviceName}/create?collectionName=${collectionName}`, {
        body: JSON.stringify(content)
    })
}

/**
 * 根据id删除数据
 * @param {id, serviceName, collectionName} object
 *  id: id
 *  serviceName: 服务名
 *  collectionName：表名
 * @returns boolean
 */
export async function deleteDocumentById({ id, serviceName, collectionName }) {
    if (!id || !serviceName || !collectionName) {
        return false
    }
    return await post(`/document/${serviceName}/delete?id=${id}&collectionName=${collectionName}`)
}